using System;
using System.Text;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Open.Data.Persistence;

using Open.Data.Persistence.Hashes;

namespace Open.Data.Persistence.Testing
{
    //Tests the abbreviations engine
    [TestClass]
    public class LabelTests
    {
        public LabelTests()
        {
        }

        [TestMethod]
        public void LabelCreateSimple()
        {
            //Create labels for the person type and the phone property
            Labels labels = new Labels(typeof(Person));

            Assert.IsTrue(labels.Count == 2, "Person abbreviations count is not valid.");

            //Get a person abbreviation and the phone abbreviation
            Type type = typeof(Person);
            TypeLabelHash hash = new TypeLabelHash(type);
            PropertyLabelHash hash2 = new PropertyLabelHash(type.GetProperty("Phone"));
            hash2.Parents.Add(hash);

            Assert.IsTrue(labels[hash] == "a", "Incorrect abbreviation return for type Person");
            Assert.IsTrue(labels[hash2] == "b", "Incorrect abbreviation return for property Phone");
        }

        [TestMethod]
        public void LabelCreateInherited()
        {
            //Get abbreviations for a customer type, person child type and phone property
            Labels labels = new Labels(typeof(Customer));

            Assert.IsTrue(labels.Count == 3, "Customer abbreviations count is not valid.");
            
            //Check the customer
            Type type = typeof(Customer);
            TypeLabelHash hash = new TypeLabelHash(type);

            Assert.IsTrue(labels[hash] == "c", "Incorrect abbreviation return for type Customer");

            //Check person and property
            Type type2 = typeof(Person);
            TypeLabelHash hash2 = new TypeLabelHash(type2);
            hash2.Parents.Add(hash);
            PropertyLabelHash hash3 = new PropertyLabelHash(type2.GetProperty("Phone"));
            hash3.Parents.Add(hash);
            hash3.Parents.Add(hash2);

            Assert.IsTrue(labels[hash2] == "a", "Incorrect abbreviation return for type Person");
            Assert.IsTrue(labels[hash3] == "b", "Incorrect abbreviation return for property Phone");
        }

        [TestMethod]
        public void LabelCreateSimpleQuery()
        {
            //Get labels for a simple person query
            //Get the query,person and the query,person,phone
            Query<Person> query = new Query<Person>();
            Labels labels = new Labels(query);

            Assert.IsTrue(labels.Count == 2, "Person Query abbreviations count is not valid.");

            QueryLabelHash hash = new QueryLabelHash(query);
            TypeLabelHash hash2 = new TypeLabelHash(typeof(Person));
            PropertyLabelHash hash3 = new PropertyLabelHash(typeof(Person).GetProperty("Phone"));

            hash2.Parents.Add(hash);

            hash3.Parents.Add(hash);
            hash3.Parents.Add(hash2);
            
            Assert.IsTrue(labels[hash2] == "a", "Incorrect abbreviation return for type Person");
            Assert.IsTrue(labels[hash3] == "b", "Incorrect abbreviation return for property Phone");
        }

        [TestMethod]
        public void LabelCreateInheritedQuery()
        {
            //Use an inherited query to get the labels for the customer, person and phone proeprties within the query
            Query<Customer> query = new Query<Customer>();
            Labels labels = new Labels(query);

            Assert.IsTrue(labels.Count == 3, "Customer Query abbreviations count is not valid.");

            QueryLabelHash hash = new QueryLabelHash(query);
            TypeLabelHash hash2 = new TypeLabelHash(typeof(Customer));

            hash2.Parents.Add(hash);

            TypeLabelHash hash3 = new TypeLabelHash(typeof(Person));
            hash3.Parents.Add(hash);
            hash3.Parents.Add(hash2);

            PropertyLabelHash hash4 = new PropertyLabelHash(typeof(Person).GetProperty("Phone"));

            hash4.Parents.Add(hash);
            hash4.Parents.Add(hash2);
            hash4.Parents.Add(hash3);

            Assert.IsTrue(labels[hash2] == "c", "Incorrect abbreviation return for type Customer");
            Assert.IsTrue(labels[hash3] == "a", "Incorrect abbreviation return for type Person");
            Assert.IsTrue(labels[hash4] == "b", "Incorrect abbreviation return for property Phone");
        }

        [TestMethod]
        public void LabelCreateComplexQuery()
        {
            //Create a complex query and get types within
            Query<Customer> customers = new Query<Customer>();
            Query<CustomerOrder> co = new Query<CustomerOrder>();
            Query<Order> orders = new Query<Order>();
            Query<OrderItem> oi = new Query<OrderItem>();
            Query<Product> product = new Query<Product>();

            Query<CustomerAddress> ca = new Query<CustomerAddress>();
            Query<Address> address = new Query<Address>();

            customers.Join(co, "Id", "CustomerId");
            co.Join(orders, "OrderId", "Id");
            orders.Join(oi, "Id", "OrderId");
            oi.Join(product, "ProductId", "Id");
            customers.Join(ca, "Id", "CustomerId");
            ca.Join(address, "AddressId", "Id");

            //Get all the abbreviations
            Labels labels = new Labels(customers);

            //Get the customer person and phone within the customer query
            QueryLabelHash query = new QueryLabelHash(customers);
            LabelHash label = new TypeLabelHash(typeof(Customer), query);
            Assert.IsTrue(labels[label] == "c", "Incorrect abbreviation return for query Customer");

            label = new TypeLabelHash(typeof(Person), label);
            Assert.IsTrue(labels[label] == "a", "Incorrect abbreviation return for query Person");

            label = new PropertyLabelHash(typeof(Person).GetProperty("Phone"), label);
            Assert.IsTrue(labels[label] == "b", "Incorrect abbreviation return for property Phone");

            //Get the customer order query
            QueryLabelHash child = new QueryLabelHash(co, query);
            label = new TypeLabelHash(typeof(CustomerOrder), child);
            Assert.IsTrue(labels[label] == "d", "Incorrect abbreviation return for query Customer Order");
        }

        [TestMethod]
        public void LabelSimpleOrdinalTest()
        {
            Order order = new Order();
            Ordinals ordinals = new Ordinals(order.GetType());
            Assert.IsTrue(ordinals.Count == 6, "Correct number of type ordinal Labels not found.");

            Query<Order> query = new Query<Order>();
            ordinals = new Ordinals(query);
            Assert.IsTrue(ordinals.Count == 6, "Correct number of query ordinal Labels not found.");

        }

        [TestMethod]
        public void LabelTestQueryHash()
        {
            Query<Customer> customers = new Query<Customer>();
            Query<CustomerOrder> cos = new Query<CustomerOrder>();
            Query<Order> orders = new Query<Order>();
            Query<OrderItem> ois = new Query<OrderItem>();
            Query<Product> products = new Query<Product>();

            customers.Join(cos, "Id", "CustomerId");
            cos.Join(orders, "OrderId", "Id");
            orders.Join(ois, "Id", "OrderId");
            ois.Join(products, "ProductId", "Id");

            LabelHash customerHash = new TypeLabelHash(customers.Type, new QueryLabelHash(customers));
            Assert.IsTrue(Common.GetQueryLabel(customers).ToString() == customerHash.ToString(), "Customers label hash not calculated correctly");

            LabelHash ordersHash = new TypeLabelHash(orders.Type, new QueryLabelHash(orders, new QueryLabelHash(cos, new QueryLabelHash(customers))));
            Assert.IsTrue(Common.GetQueryLabel(orders).ToString() == ordersHash.ToString(), "Orders label hash not calculated correctly");
        }
    }
}
